<script setup lang="tsx">
import {
  Box,
  Delete,
  Edit,
  Plus,
  Warning,
} from '@element-plus/icons-vue'
import type {
  Action,
} from 'element-plus'
import {
  ElSwitch,
  ElTag,
  ElTree,
} from 'element-plus'
import { FormModal } from './components'
import { defaultForm } from '.'
import {
  sysApplicationApi,
  sysApplicationMenuApi,
  sysMenuApi,
} from '@/api'
import type {
  ApplicationInfo,
  ApplicationMenuInfo,
  ApplicationSaveOrUpdateParams,
  ApplicationUpdateBindMenuParams,
  MenuInfo,
  TableColumn,
} from '@/types'
// ------------------use------------------
// #region
const { getPower } = usePagePower()
const { $confirm, $message } = useCurrentInstance()
const { vLoading, withLoading, loading }
  = useDefineLoading()
const [applyData, setApplyData] = useState<
  ApplicationInfo[]
>([])
const [formData, setFormData] = useState<
  Partial<ApplicationSaveOrUpdateParams>
>({
  ...defaultForm,
})
const [formModalTitle, setFormModalTitle]
  = useState<string>('')
const [selectApply, setSelectApply]
  = useState<ApplicationInfo>({} as any)
const [menuData, setMenuData] = useState<MenuInfo[]>([])
const [bindMenuData, setBindMenuData] = useState<
  Required<ApplicationMenuInfo>[]
>([])
const [isAssignmentsMenu, setIsAssignmentsMenu]
  = useState<boolean>(false)
// #endregion
// ------------------静态变量------------------
// #region
const columns: TableColumn<
  Required<ApplicationMenuInfo>
>[] = [
  {
    key: uuid(),
    prop: 'menuId',
    width: '80',
    label: 'ID',
    fixed: true,
  },
  {
    key: uuid(),
    label: '菜单名称',
    prop: 'menuName',
    fixed: true,
  },
  {
    key: uuid(),
    label: '菜单标题',
    prop: 'menuTitle',
    header: () => {
      return (
        <span class="align-center flex justify-center">
          菜单标题
          <el-tooltip
            content="页签显示标题，默认为菜单名称"
            placement="top"
          >
            <el-icon class="c-pointer margin-left-xs text-orange">
              <Warning />
            </el-icon>
          </el-tooltip>
        </span>
      )
    },
    render: ({ row }) => {
      return row.menuTitle || row.menuName
    },
  },
  {
    key: uuid(),
    label: '启用',
    header: () => {
      return (
        <span class="align-center flex justify-center">
          启用
          <el-tooltip
            content="页面不会注册"
            placement="top"
          >
            <el-icon class="c-pointer margin-left-xs text-orange">
              <Warning />
            </el-icon>
          </el-tooltip>
        </span>
      )
    },
    render({ row }) {
      return h(ElSwitch, {
        modelValue: row.enable,
        activeValue: 1,
        inactiveValue: 0,
        disabled: !getPower('edit'),
        onclick: () => {
          handlerSwitchStatus(row, 'enable')
        },
      })
    },
  },
  {
    key: uuid(),
    label: '菜单标识',
    prop: 'identifying',
  },
  {
    key: uuid(),
    label: '菜单路径',
    prop: 'menuAddress',
  },
  {
    key: uuid(),
    label: '重定向',
    header: () => {
      return (
        <span class="align-center flex justify-center">
          重定向
          <el-tooltip
            content="用于跳转到第三方平台"
            placement="top"
          >
            <el-icon class="c-pointer margin-left-xs text-orange">
              <Warning />
            </el-icon>
          </el-tooltip>
        </span>
      )
    },
    prop: 'redirect',
  },
  {
    key: uuid(),
    label: '菜单类型',
    render({ row }) {
      if (!row.menuType)
        return ''
      if (row.menuType === 1) {
        return h(ElTag, null, {
          default: () => '目录',
        })
      }
      else if (row.menuType === 2) {
        return h(
          ElTag,
          {
            type: 'success',
          },
          {
            default: () => '菜单',
          },
        )
      }
      else {
        return h(
          ElTag,
          {
            type: 'warning',
          },
          {
            default: () => '按钮',
          },
        )
      }
    },
  },
  {
    key: uuid(),
    label: '菜单图标',
    prop: 'menuIcon',
  },
]
// #endregion
// ------------------动态变量------------------
// #region

// #endregion
// ------------------ref-----------
// #region
const modalRef = ref<InstanceType<typeof FormModal>>()
const treeRef = ref<InstanceType<typeof ElTree>>()
// #endregion
// ------------------reactive------
// #region

// #endregion
// ------------------computed------
// #region
// const handlerMenuData = computed(() =>
//   menuData.value.filter(item => !(item.menuType === 0 || item.menuEnable === 1))
// );
// #endregion
// ------------------生命周期------------------
// #region
onMounted(() => {
  getApplyData()
  getMenuData()
})
// #endregion
// ------------------内置方法---------------------
// #region

// #endregion
// ------------------方法---------------------
// #region
async function getApplyData() {
  const { data: res } = await withLoading(
    sysApplicationApi.queryList,
  )()
  setApplyData(res)
  if (res.length === 0)
    return
  setSelectApply(res[0]!)
  getBindMenuData()
}
async function getMenuData() {
  const { data: res } = await withLoading(
    sysMenuApi.queryTreeList,
  )()
  setMenuData(res)
}
async function getBindMenuData() {
  const { data: res } = await withLoading(
    sysApplicationMenuApi.queryBindMenuTree,
  )({
    applicationId: selectApply.value.id,
  })

  setBindMenuData(res)
}
async function getBindMenuIdData() {
  const { data } = await withLoading(
    sysApplicationMenuApi.queryBindMenuId,
    'tree',
  )(selectApply.value.id)
  treeRef.value?.setCheckedKeys(data)
}
async function showAssignmentsMenuDialog() {
  setIsAssignmentsMenu(true)
  await nextTick()
  getBindMenuIdData()
}
async function saveOrUpdate(params: Partial<ApplicationSaveOrUpdateParams>) {
  removeUnnecessaryParams(params)
  const { code } = await sysApplicationApi.saveOrUpdate(
    params,
  )
  if (code !== 200)
    return
  getApplyData()
  modalRef.value?.close()
  $message.success('保存成功！')
}
async function assignmentsMenu() {
  const keys = treeRef.value?.getCheckedKeys()
  if (!keys || keys?.length === 0)
    return
  const n = keys.map(key => ({
    menuId: key as number,
    applicationId: selectApply.value.id,
    enable: selectApply.value.applicationEnable,
  }))
  const { code } = await sysApplicationMenuApi.batchMenuId(
    n,
  )
  if (code !== 200)
    return
  setIsAssignmentsMenu(false)
  getBindMenuData()
  $message.success('菜单分配成功！')
}
/** 删除数据 */
async function deleteData(id: number) {
  const res: Action = await $confirm(
    '该操作将永久删除该应用，确定删除？',
    '警告',
    {
      type: 'warning',
    },
  ).catch(e => e)

  if (res !== 'confirm')
    return
  const { code } = await sysApplicationApi.deleteById(id)
  if (code !== 200)
    return
  getApplyData()
}
async function showAddDialog() {
  modalRef.value?.open()
  await nextTick()
  setFormModalTitle('新增')
  setFormData({
    ...defaultForm,
  })
}
async function showEditDialog(row: ApplicationInfo) {
  modalRef.value?.open()
  await nextTick()
  setFormModalTitle('编辑')
  setFormData({
    ...defaultForm,
    ...row,
  })
}
function switchApply(row: ApplicationInfo) {
  setSelectApply(row)
  getBindMenuData()
}
async function handlerSwitchStatus(row: Required<ApplicationMenuInfo>, str: string) {
  const params: ApplicationUpdateBindMenuParams = {
    applicationId: selectApply.value.id,
    menuId: row.menuId,
    enable: +!(row as any)[str],
  }
  const { code }
    = await sysApplicationMenuApi.updateBindMenu(params)
  if (code !== 200)
    return
  getBindMenuData()
}
// #endregion
</script>

<template>
  <div
    class="padding-sm align-center purview flex gap-sm container"
  >
    <b-scrollbar
      v-loading
      class="panel height-fill flex-incompressible flex-direction padding-sm purview-left box-border flex gap-sm"
    >
      <div
        class="panel-header flex-incompressible align-center width-fill flex"
      >
        <h5 class="margin-0 margin-right-auto">
          所有应用
        </h5>
        <TdButton
          title="新增应用"
          :icon="Plus"
          type="primary"
          @click="showAddDialog"
        />
      </div>
      <ul class="panel-list">
        <li
          v-for="item in applyData"
          :key="item.id"
          class="fs-14 padding-lr-xs c-pointer align-center box-border flex"
          :class="[
            {
              active: selectApply.id === item.id,
            },
          ]"
          @click="switchApply(item)"
        >
          <span
            class="flex-fillRemaining text-overflow-hide"
          >
            {{ item.applicationName }}
          </span>
          <div class="margin-left-auto flex-incompressible">
            <el-button
              link
              :disabled="!getPower('edit')"
              :icon="Edit"
              type="primary"
              @click.stop.prevent="showEditDialog(item)"
            />
            <el-button
              link
              :disabled="!getPower('delete')"
              :icon="Delete"
              type="danger"
              @click.stop.prevent="deleteData(item.id)"
            />
          </div>
        </li>
      </ul>
    </b-scrollbar>
    <div
      class="align-center flex-direction flex-fillRemaining overflow height-fill flex"
    >
      <view-table
        :loading="loading"
        :columns="columns"
        :data="bindMenuData"
        row-key="menuId"
      >
        <template #actions>
          <el-button
            :disabled="!getPower('edit')"
            plain
            type="primary"
            :icon="Box"
            @click="showAssignmentsMenuDialog"
          >
            分配菜单
          </el-button>
        </template>
      </view-table>
    </div>
    <FormModal
      ref="modalRef"
      :title="formModalTitle"
      :data="formData"
      @save-success="saveOrUpdate(formData)"
    />
    <!-- 分配菜单 -->
    <el-dialog
      v-model="isAssignmentsMenu"
      width="600"
      title="分配菜单"
      append-to-body
    >
      <ElTree
        ref="treeRef"
        v-loading="{
          space: 'tree',
        }"
        check-strictly
        accordion
        :props="{
          label: 'menuName',
        }"
        node-key="id"
        :data="menuData"
        show-checkbox
      />
      <template #footer>
        <el-button @click="setIsAssignmentsMenu(false)">
          取 消
        </el-button>
        <el-button type="primary" @click="assignmentsMenu">
          确 定
        </el-button>
      </template>
    </el-dialog>
  </div>
</template>

<style lang="scss" scoped>
.purview {
  --purview-lw: 300px;
  &-left {
    background-color: var(--el-bg-color);
    border: 1px solid var(--el-border-color-light);
    border-radius: 4px;
    width: var(--purview-lw);

    transition: all var(--motion-bezier) 0.3s;
    &:hover {
      box-shadow: 0 8px 32px #0000000d;
    }
  }
  &-right {
    &__header {
      border-left: 4px solid var(--el-color-primary);
    }
  }
}
.panel-list {
  li > div {
    opacity: 0;
  }
  li:not(.active):hover > div,
  li.active > div {
    opacity: 1;
  }
}
.b-scrollbar {
  scroll-snap-type: none;
}
//------------------组件样式------------------
//-------------样式穿透-------------
</style>
